/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tbgb.components.state;

/**
 *
 * @author Salm
 */
public class MultiStateComponent implements StateComponent{
    private static final int INTEGER_NUMBEROFBITS = 32;
    
    private Integer state = new Integer(0);
    private int[] bitIndices;
    
    public MultiStateComponent(int[] nStatesValues)
    {
        this.bitIndices = nStatesValues;
        this.convertNumberOfValuesToBitIndicies(nStatesValues);
    }
    
    public Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
    }
    
    public int getState(int index)
    {
        if (index < 0 || index >= this.bitIndices.length)
        {
            return Integer.MIN_VALUE;
        }
        
        int bitIndex = this.bitIndices[index];
        int nextIndex = (index == bitIndices.length)?INTEGER_NUMBEROFBITS:(bitIndices[index + 1]);
        
        int nLeftBits = INTEGER_NUMBEROFBITS - nextIndex;
        int nRightBits = nLeftBits + bitIndex;
        
        return (this.state.intValue()<<nLeftBits)>>nRightBits;
    }
    
    public void setState(int index, int stValue)
    {
        if (index < 0 || index >= this.bitIndices.length)
        {
            return;
        }
        int newState = this.state.intValue();
        
        int bitIndex = this.bitIndices[index];
        int nextIndex = (index == bitIndices.length)?INTEGER_NUMBEROFBITS:(bitIndices[index + 1]);
        
        // reset bits
        int negMaskBits = ~this.createMaskBits(bitIndex, nextIndex);
        newState &= negMaskBits;
        
        newState |= stValue<<bitIndex;
        
        this.state = new Integer(newState);
    }
    
    private int[] convertNumberOfValuesToBitIndicies(int[] nValues)
    {
        int[] bInds = new int[nValues.length];
        for (int i = 1; i < nValues.length; i++) {
            bInds[i] = bInds[i - 1] + this.findNumberOfBits(nValues[i - 1]);
        }
        
        return bInds;
    }

    private static final int MASK_ALL = 0xffffffff;
    private int createMaskBits(int bitIndex, int nextIndex) {
        return (MASK_ALL<<(INTEGER_NUMBEROFBITS - nextIndex))>>
                (INTEGER_NUMBEROFBITS - nextIndex + bitIndex);
    }
    
    private int findNumberOfBits(int value)
    {
        //zero is one value
        --value;
        
        int nBits = 0;
        while (value > 0)
        {
            value >>= 1;
            ++nBits;
        }
        
        return nBits;
    }
}
